/**
 * @author wn
 * @date 2023/02/01 11:59:02
 * @description: prototype Class 笔记
 */

// 构造函数
function MakePerson(name) {
	// this  是 实例对象  也就是 实例添加了 name sing  属性 与方法  value 由实例化时 决定
	this.name = name
	// 多个实例 多个指向  开辟多个内存空间  函数是复杂数据类型  多个 占用内存
	this.sing = function () {}
}
const person = new MakePerson('aa')
const name = person.name // 通过 构造函数中 this  实例 有了该属性

// 静态 属性 方法  --  在构造函数本身上添加
// 只能通过构造函数本省调用 MakePerson.sex;  person不可
MakePerson.sex = '男'

// 原型对象 -- prototype
// 构造函数 -- prototype  所有实例共享
MakePerson.prototype.sing2 = function () {}
person.sing2()

// 实例对象 person身上系统自动添加了__proto__指向构造函数原型对象
person.__proto__ === MakePerson.prototype

// 指回构造函数
MakePerson.prototype.constructor = MakePerson

// 原型链
person.__proto__ === MakePerson.prototype
MakePerson.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null //到顶了

// 语法糖 class
class MakePerson2 {
	// 必须有 constructor 方法，如果没有显式定义，一个默认的 constructor 方法会被默认添加
	// new 命令创建对象实例时，自动调用该方法
	constructor(name) {
		this.name = name // this 指 实例对象
	}
	sing() {} // MakePerson2.prototype.sing = function () {} 实例调用 共享
	static sex = '男'
}
const per = new MakePerson2('name')
per.name
per.sing()

// 继承  1借用 构造函数 继承属性  2原型对象 继承方法   组合继承
function Father(name) {
	this.name = name
}
Father.prototype.work = function () {}

function Son(name) {
	/**
	 * Son实例 继承 Father name 属性
	 * this指向  子构造函数对象实例
	 * 相当于父亲里面  son.name = name;
	 */
	Father.call(this, name)
}
// Son.prototype = Father.prototype;    有问题修改子原型对象，父原型对象一起变化,地址相同
Son.prototype = new Father()
// 利用对象的形式修改了原型对象，需要重新指回原来的构造函数
Son.prototype.constructor = Son
// son.__proto__ === Son.prototype === new Father.__proto__ === Father.prototype;

// 等价于上面 两行
Son.prototype = Object.create(Father.prototype)

// 语法糖 class extends super
class Father2 {
	constructor(name) {
		this.name = name
	}
	work() {
		console.log(this) // super 调用  this  指向 子类实例
	}
}

// 继承父类的属性和方法    可以理解为  super代替了 call   extends 代替了 prototype
class Son extends Father2 {
	constructor(name, age) {
		super(name)
		this.age = age
		// super.name   无法通过super 访问父类 实例属性
	}
}
/**
 * super 必须在  constructor 中  必须有
 * 必须在 this 之前
 * super 作为函数 代表父类构造方法  但是this指向子类实例
 * super 作为对象 父类原型对象  Father.prototype
 * super调用父类方法时 方法内部 this 指向 子类实例
 * super在静态方法中指向父类 而不是父类原型对象
 * super在静态方法调用父类方法时 方法内部 this 指向 当前子类 而不是子类实例
 */
